package com.googlecode.contests_repo.zip;

import java.io.File;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import com.googlecode.contests_repo.annotation.ResourcePrivate;
import com.googlecode.contests_repo.core.model.Problem;
import com.googlecode.contests_repo.core.model.ReflectionUtils;
import com.googlecode.contests_repo.core.model.ResourcesUtils;
import com.googlecode.contests_repo.core.users.AccessRight;

/**
 * A {@link ResourceZiper} for {@link Problem}s. 
 * 
 * @author deni, boyan
 */
public class ProblemZiper extends ResourceZiper {

	@Override
	public void processJsonFile(AccessRight right, String resourcePath,
			String zipPath, ZipOutputStream zip) throws JsonParseException,
			JsonMappingException, IOException {
		ObjectMapper mapper = new ObjectMapper();
		File problemJsonFile = new File(resourcePath + File.separator + "problem.json");
		Problem problem = mapper.readValue(problemJsonFile, Problem.class);
				
		if (!right.includes(AccessRight.VIEW_FULL)) {
			ReflectionUtils.setAnnotatedFields(problem, ResourcePrivate.class, null);
			
			if (!ResourcesUtils.hasContestFinished(new File(resourcePath).getParentFile())) {
				problem.setTestWeights(null);
			}
		}
	
		String path = getExtendedFilePath(zipPath, "problem.json");
		zip.putNextEntry(new ZipEntry(path));

		byte[] bytes = mapper.writeValueAsBytes(problem);
		zip.write(bytes);		
	}

	@Override
	public ResourceZiper getChildZiper() {
		return null;
	}

	public void processResourceSpecificFiles(AccessRight right, String resourcePath,
			String zipPath, ZipOutputStream zip) throws Exception {
		
		File problemDir = new File(resourcePath);
		File contestDir = problemDir.getParentFile();
		if (right.includes(AccessRight.VIEW_FULL) || ResourcesUtils.hasContestStarted(contestDir)) {
			File[] descriptionFiles = ResourcesUtils.getProblemDescriptionFiles(problemDir);
			for (File description : descriptionFiles) {
				addFileToZip(description.getPath(), zipPath, zip);
			}
		}
		
		if (right.includes(AccessRight.VIEW_FULL)) {
			File[] testFiles = ResourcesUtils.getProblemTestFiles(problemDir);
			for (File test : testFiles) {
				addFileToZip(test.getPath(), zipPath, zip);
			}
			
			File[] solutionFiles = ResourcesUtils.getProblemSolutionFiles(problemDir);
			for (File solution : solutionFiles) {
				addFileToZip(solution.getPath(), zipPath, zip);
			}
			
			File checker = ResourcesUtils.getProblemCheckerFile(problemDir);
			if (checker != null) {
				addFileToZip(checker.getPath(), zipPath, zip);
			}
		}
	}
	
	protected boolean shouldIncludeChildResources(String resourcePath, AccessRight right) {
		if (!super.shouldIncludeChildResources(resourcePath, right)) {
			return false;
		}
		return  right.includes(AccessRight.VIEW_FULL) ||
				ResourcesUtils.hasContestStarted(new File(resourcePath).getParentFile());
	}
	
	protected boolean shouldIncludePublicFiles(String resourcePath, AccessRight right) {
		if (!super.shouldIncludePublicFiles(resourcePath, right)) {
			return false;
		}
		return  right.includes(AccessRight.VIEW_FULL) ||
				ResourcesUtils.hasContestStarted(new File(resourcePath).getParentFile());
	}
}
